You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
2.1 KiB
60 lines
2.1 KiB
import { getRequestIP } from "h3";
|
|
import { getPublicPostCommentContext } from "#server/service/posts";
|
|
import { createComment } from "#server/service/post-comments";
|
|
import { notifyReplyCommentCreated } from "#server/service/comment-notify";
|
|
import { assertUnderRateLimit } from "#server/utils/simple-rate-limit";
|
|
import { parsePublicPostCreateCommentBody } from "#server/api/public/comments-create-body";
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const publicSlug = event.context.params?.publicSlug;
|
|
const postSlug = event.context.params?.postSlug;
|
|
if (!publicSlug || !postSlug || typeof publicSlug !== "string" || typeof postSlug !== "string") {
|
|
throw createError({ statusCode: 400, statusMessage: "无效请求" });
|
|
}
|
|
|
|
const ctx = await getPublicPostCommentContext(publicSlug, postSlug);
|
|
if (!ctx) {
|
|
throw createError({ statusCode: 404, statusMessage: "未找到" });
|
|
}
|
|
|
|
const viewer = await event.context.auth.getCurrent();
|
|
const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown";
|
|
if (viewer == null) {
|
|
assertUnderRateLimit(`comment-post-guest:${ip}`, 20, 15 * 60 * 1000);
|
|
} else {
|
|
assertUnderRateLimit(`comment-post-user:${viewer.id}`, 60, 15 * 60 * 1000);
|
|
}
|
|
|
|
const body = await readBody<{
|
|
parentId?: number | null;
|
|
guestDisplayName?: string;
|
|
guestEmail?: string;
|
|
guestIsAnonymous?: boolean;
|
|
body: unknown;
|
|
}>(event);
|
|
|
|
const parsed = parsePublicPostCreateCommentBody(body);
|
|
|
|
const newCommentId = await createComment({
|
|
postId: ctx.id,
|
|
ownerUserId: ctx.userId,
|
|
parentId: parsed.parentId,
|
|
viewer,
|
|
guestDisplayName: parsed.guestDisplayName,
|
|
guestEmail: parsed.guestEmail,
|
|
guestIsAnonymous: parsed.guestIsAnonymous,
|
|
body: parsed.body,
|
|
});
|
|
|
|
void notifyReplyCommentCreated({
|
|
postId: ctx.id,
|
|
postOwnerUserId: ctx.userId,
|
|
commentId: newCommentId,
|
|
parentId: parsed.parentId,
|
|
actorUserId: viewer?.id ?? null,
|
|
actorGuestEmail: viewer == null ? (parsed.guestEmail ?? null) : null,
|
|
replyBody: parsed.body,
|
|
});
|
|
|
|
return R.success({ id: newCommentId });
|
|
});
|
|
|